package com.dkts.oil.router.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.dkts.oil.config.OilConfig;
import com.dkts.oil.router.RouteStrategy;
import com.dkts.oil.router.param.PathInfo;
import com.dkts.oil.router.param.RouterInfo;
import com.dkts.oil.router.thread.LycToZyRouteTask;
import com.dkts.oil.service.impl.OilAddressV2Helper;
import com.dkts.oil.util.HttpUtils;
import com.dkts.oil.web.vo.request.RouteCommonRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;

/**
 * 1.1.2.2.1 炼油厂到转运站运输路线规划
 * 功能名称	炼油厂到转运站运输路线规划	功能标识	CADS_02_001
 * 功能描述	根据转运站位置判断是否使用铁路运输还是水路运输（水路只考虑长江中下游与珠江流域）。如果采用铁路运输，根据火车站与炼油厂位置；如果采用水路根据港口与炼油厂位置，通过GIS交通网络进行炼油厂到转运站运输路线规划，并生成筹措运输方案
 * 输入	转运站位置、炼油厂位置
 * 处理逻辑	1）	判断转运站位置，是否靠近在长江中下游或珠江流域附近，如果靠近则规划水路运输，否则规划铁路运输
 * 2）	水路运输规划从炼油厂到转运站最合适点的位置，然后规划一条需要挖掘的水路到达转运站
 * 3）	铁路运输规划从炼油厂到转运站最近火车站的铁路运输路线，然后规划一条需要修改建的从火车站到转运站的铁路线，在规划铁路线时需要考虑路线规划约束条件
 * 4）	保存路线规划结果，在GIS地图上展示规划路线，已有路线与新建路线采用不同线路样式进行标识
 * 5）	计算运输用时，并生成油料筹措方案
 * 输出	运输路线（包括新建或新修的水路或铁路线）、运输预计用时、筹措方案（说明从炼油厂到转运站路线说明，包括路线长度、运输平均速度、预计用时、运输量）
 *
 *
 *1.炼油厂到ZYZ规划逻辑：
 * 若规划铁路，只需规划第二、三段
 * 第一段：炼油厂——>火车站（距离炼油厂最近）【新增路线】 - 这个不需要规划，如果没有铁路线就找最近的火车站
 * 第二段：火车站（距离炼油厂最近）——>火车站（距离ZYZ最近）【已有路线】
 * 第三段：火车站（距离ZYZ最近）——>ZYZ【新增路线】
 * 若规划水路，只需规划第二段
 * 第一段：炼油厂——>港口/码头（距离炼油厂最近）【新增路线】-这个不需要规划
 * 第二段：港口/码头（距离炼油厂最近）——>港口/码头（距离ZYZ最近）【已有路线，沿着长江或者珠江即可】
 * 第三段：港口/码头（距离ZYZ最近）——>ZYZ【新增路线】-这个不需要规划
 * 2.其他油库到ZYZ规划逻辑：
 * 需规划第一、二、三段
 * 第一段：其他油库——>最佳点A（已有公路上）【新增路线】 - 这个不需要规划
 *
 * 第二段：最佳点A（已有公路上）——>最佳点B（已有公路上）【已有路线】
 * 第三段：最佳点B（已有公路上）——>ZYZ【新增路线】
 */
@Service("LYC_TO_ZY")
public class LycToZyStrategy extends RouterCommonHelper implements RouteStrategy<RouteCommonRequest, RouterInfo> {

    @Autowired
    private OilConfig oilConfig;

    @Autowired
    private ThreadPoolTaskExecutor taskExecutor;

    @Override
    public RouterInfo planRoute(RouteCommonRequest param) {
        param.setLocalRouteDistance(1D);
        param.setCreateNewRoadDistance(1D);
        RouterInfo[] roadResult = new RouterInfo[1];
        RouterInfo[] waterResult = new RouterInfo[1];
        execute(roadResult, waterResult, param);
        return merge(roadResult[0], waterResult[0]);
    }


    private void execute(RouterInfo[] roadResult, RouterInfo[] waterResult, RouteCommonRequest param) {
        CountDownLatch latch = new CountDownLatch(2);
        //如果没有铁路线就找最近的火车站 todo ?
        taskExecutor.execute(new LycToZyRouteTask(
                param,
                oilConfig.getRailwayUrl() + "/route",
                result -> roadResult[0] = result,
                latch,
                this, "car", 2,param.getCreateNewRoadDistance(), param.getLocalRouteDistance()
        ));
        taskExecutor.execute(new LycToZyRouteTask(
                param,
                oilConfig.getWaterwayUrl() + "/route",
                result -> waterResult[0] = result,
                latch,
                this, "small_truck", 3,param.getCreateNewRoadDistance(), param.getLocalRouteDistance()
        ));
        try {
            latch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }

    public RouterInfo getRouterAll(RouteCommonRequest param, String url, String profile, Integer type,Double distance,Double localRoute) {
        JSONObject result = this.getRouteParam(param.getPoints(), profile);
        JSONArray data = HttpUtils.postRouteOil(url, JSONObject.toJSONString(result), param.getPoints());
        return parseAllRouteSegments(data, param.getRouteModel(), type,distance,2,localRoute);
    }

//    public RouterInfo routerEndSegments(JSONArray pathsArray, String routerModel, Integer type, Double distance) {
//
//
//        List<PathInfo> allSegments = new ArrayList<>();
//
//        for (int i = 0; i < pathsArray.size(); i++) {
//            JSONObject pathObj = pathsArray.getJSONObject(i);
//            PathInfo segments = parseRouteSegments(pathObj);
//            segments.setFundInfo(OilAddressV2Helper.summarizeInstructions(segments.getInstructions()));
//            //判断是否需要创建的公路
//            setEndRoadData(segments, distance);
//            allSegments.add(segments);
//        }
//        return new RouterInfo(allSegments, routerModel, type);
//    }

    public RouterInfo merge(RouterInfo railway, RouterInfo waterRouter) {
        PathInfo raiPath= railway.getPaths().get(0);
        PathInfo watPath= waterRouter.getPaths().get(0);
        PathInfo.CreateRoadSegments rs= RouterCommonHelper.createRoadSegmentsDist(raiPath.getRoadInfos().get(0).getCoordinates().getJSONArray(0),raiPath.getRoadInfos().get(0).getCoordinates().getJSONArray(1));
        PathInfo.CreateRoadSegments ws= RouterCommonHelper.createRoadSegmentsDist(watPath.getRoadInfos().get(0).getCoordinates().getJSONArray(0),watPath.getRoadInfos().get(0).getCoordinates().getJSONArray(1));


        double rDistanceStart = rs.getDistance();
        double wDistanceStart = ws.getDistance();

        PathInfo.CreateRoadSegments rEnd =railway.getPaths().get(0).getEndNewRoad();
        PathInfo.CreateRoadSegments wEnd =waterRouter.getPaths().get(0).getEndNewRoad();
        double rDistanceEnd = 0d;

        if (rEnd != null) {
            rDistanceEnd = rEnd.getDistance();
        }else {
            int row= raiPath.getRoadInfos().get(0).getCoordinates().size();
            rDistanceEnd=  RouterCommonHelper.createRoadSegmentsDist(raiPath.getRoadInfos().get(0).getCoordinates().getJSONArray(row-2),raiPath.getRoadInfos().get(0).getCoordinates().getJSONArray(row-1)).getDistance();
        }

        double wDistanceEnd = 0D;
        if (wEnd != null) {
            wDistanceEnd = wEnd.getDistance();
        }else {
            int row= watPath.getRoadInfos().get(0).getCoordinates().size();
            wDistanceEnd =  RouterCommonHelper.createRoadSegmentsDist(watPath.getRoadInfos().get(0).getCoordinates().getJSONArray(row-2),watPath.getRoadInfos().get(0).getCoordinates().getJSONArray(row-1)).getDistance();;
        }


        double rAllDistance = railway.getPaths().get(0).getDistance();
        double wAllDistance = waterRouter.getPaths().get(0).getDistance();

        if (wDistanceStart < 2000 && wDistanceEnd < 2000) {
            return waterRouter;
        }


        //两个都小于肯定是做铁路
        if (rDistanceStart < wDistanceStart && rDistanceEnd < wDistanceEnd) {
            return railway;
        }
        if (rDistanceStart < wDistanceStart) {
            return railway;
        }

        if (wAllDistance < rAllDistance) {
            return waterRouter;
        }

        if (wDistanceStart < rDistanceStart && rDistanceStart - wDistanceStart < 1000) {
            return waterRouter;
        }

        return railway;
    }
}
